package com.light.component;

import atlantafx.base.theme.Styles;
import com.light.exception.AuthException;
import com.light.exception.JGitException;
import com.light.exception.TimeOutException;
import com.light.layout.NavItem;
import com.light.model.GitAuthInfo;
import com.light.model.GitProject;
import com.light.thread.FxAsyncTask;
import com.light.util.DateUtils;
import com.light.util.FxApplicationContextUtils;
import com.light.util.H2PoolUtils;
import com.light.util.JGitUtils;
import com.light.view.ManagerView;
import javafx.application.Platform;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.layout.HBox;
import javafx.util.Callback;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.Date;

/**
 * 操作列 - 按钮
 */
public class OperationTableCell extends TableCell<GitProject, Integer> {

    public static final Logger LOGGER = LoggerFactory.getLogger(OperationTableCell.class);
    Button updateButton = new Button("更新");
    Button detailButton = new Button("详情");
    HBox operationBox = new HBox(updateButton, detailButton);
    private SimpleDoubleProperty rate;

    public static Callback<TableColumn<GitProject, Integer>, TableCell<GitProject, Integer>> forTableColumn() {
        return param -> new OperationTableCell();
    }

    public OperationTableCell() {
        updateButton.getStyleClass().addAll(Styles.FLAT, Styles.ACCENT);
        updateButton.setMnemonicParsing(true);
        detailButton.getStyleClass().addAll(Styles.FLAT, Styles.SUCCESS);
        detailButton.setMnemonicParsing(true);
        operationBox.setAlignment(Pos.CENTER_LEFT);
        initEvent();
    }

    @Override
    protected void updateItem(Integer item, boolean empty) {
        super.updateItem(item, empty);
        if (empty || getTableRow() == null || null == item) {
            setGraphic(null);
        } else {
            rate = null;
            GitProject project = getTableRow().getItem();
            if (null != project) {
                rate = project.downloadRate();
            }
            setGraphic(operationBox);
        }
    }

    private void initEvent() {
        detailButton.setOnAction(event -> {
            GitProject project = getTableRow().getItem();
            ListView<NavItem> dynamicMenu = (ListView<NavItem>) FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.get("menu");
            dynamicMenu.setUserData(project);
            dynamicMenu.getSelectionModel().selectLast();
        });
        updateButton.setOnMouseClicked(event -> {
            JGitUtils.GITHUB_FAIL_NUMBER.set(0);
            JGitUtils.GITEE_FAIL_NUMBER.set(0);
            updateButton.setDisable(true);
            rate.set(0.0);
            GitProject project = getTableRow().getItem();
            if (null != project) {
                // 更新更新数量+1
                FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.incrementAndGet()));

                String message = "更新项目";
                long startTime = System.currentTimeMillis();
                FxAsyncTask.runOnceTask(message, new Task<Object>() {
                    private AuthenticationPane authPane;

                    @Override
                    protected Object call() throws Exception {
                        File localRepoFile = new File(project.local().get());
                        String remoteUrl = project.remote();
                        try {
                            authPane = null;
                            ManagerView.pull(project, localRepoFile, remoteUrl, rate);
                        } catch (AuthException e) {
                            authPane = AuthenticationPane.getInstance();
                            authPane.refreshData(remoteUrl, (username, password) -> {
                                GitAuthInfo authInfo = authPane.dealAuthInfo(username, password, JGitUtils.getType(remoteUrl));
                                if (authInfo != null) {
                                    // 更新
                                    // 更新更新数量+1
                                    FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.incrementAndGet()));
                                    try {
                                        CredentialsProvider provider = JGitUtils.createCredential(username, password);
                                        boolean pull = JGitUtils.pull(remoteUrl, localRepoFile, provider, rate);
                                        if (pull) {
                                            project.updateTime().set(DateUtils.formatDateTime(new Date()));
                                            H2PoolUtils.updateGitProject(project);
                                            project.selected().set(false);
                                        }
                                    } catch (AuthException e1) {
                                        // 弹出输入权限界面
                                        Platform.runLater(() -> authPane.show((Scene) FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.get("scene")));
                                    } catch (TimeOutException | JGitException ignored) {

                                    }
                                    // 更新更新数量-1
                                    FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.decrementAndGet()));
                                }
                            });
                            throw new AuthException();
                        }
                        return null;
                    }

                    @Override
                    protected void succeeded() {
                        super.succeeded();
                        // 更新更新数量-1
                        authPane = null;
                        FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.decrementAndGet()));
                        updateButton.setDisable(false);
                        LOGGER.info("Task {} 执行成功，耗时 {} ms", message, System.currentTimeMillis() - startTime);
                    }

                    @Override
                    protected void failed() {
                        super.failed();
                        if (authPane != null) {
                            authPane.show((Scene) FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.get("scene"));
                        }
                        // 更新更新数量-1
                        FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.decrementAndGet()));
                        updateButton.setDisable(false);
                        LOGGER.info("Task {} 执行失败，耗时 {} ms", message, System.currentTimeMillis() - startTime);
                    }
                });
            }
        });
    }
}
